#include <Arduino.h>
#include "WiFi.h"
#include "common.h"

#include <HardwareSerial.h>

HardwareSerial serialPort1(1);

#define QUEUE_ITEM_NUM  300
#define DATA_BUF_SIZE 100

#define WIFI_SSID       "ESP32_UART"
#define WIFI_PASSWORD   "1234567890"

class Data
{
public:
    uint32_t len;
    uint8_t buf[DATA_BUF_SIZE];
};

static xQueueHandle xQueueSerial=NULL;
static xQueueHandle xQueueTCP=NULL;


WiFiClient client;
int timeout = 0;
WiFiUDP udp;

static TaskHandle_t xSerialTask = NULL;

void serial_on_receive(void)
{
    Data data;
    int bytes_to_read = 0;
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    while(serialPort1.available())
    {
        bytes_to_read = serialPort1.available();
        if(bytes_to_read > 0)
        {
            if(bytes_to_read > DATA_BUF_SIZE)
            {
                bytes_to_read = DATA_BUF_SIZE;
            }

            data.len = serialPort1.read(data.buf,bytes_to_read);
            if(data.len)
            {
                xQueueSendFromISR(xQueueSerial,&data,&xHigherPriorityTaskWoken);
            }
        }
    }
}

void serial_task(void * args)
{
    Data data;

    serialPort1.onReceive(serial_on_receive, false); 

    for(;;)
    {
        if(xQueueReceive(xQueueTCP,&data,10)==pdPASS)
        {
            serialPort1.write(data.buf,data.len);
        }
    }
}

static TaskHandle_t xTcpTask = NULL;
void tcp_task(void * args)
{
    Data data;
    char str[DATA_BUF_SIZE * 2];
    int str_len=0;
    int bytes_to_read = 0;

    for(;;)
    {
        if(millis()%1000 == 0)
        {
            led_control(0);
        }
        if(millis()%1000 == 500)
        {
            led_control(1);
        }

        while(WiFi.status() != WL_CONNECTED)
        {
            WiFi.begin(WIFI_SSID,WIFI_PASSWORD);
            delay(100);
            if(WiFi.status() == WL_CONNECTED)
            {
                Serial.println("");
                Serial.println("WiFi connected");
                Serial.println("IP address: ");
                Serial.println(WiFi.localIP());
            }
            else
            {
                delay(100);
                led_control(0);
                delay(100);
                led_control(1);
                delay(100);
                led_control(0);
                delay(100);
                led_control(1);
                Serial.print(".");
            }
        }

        client.connect("192.168.4.1", 8000);
        while(client.connected())
        {
            bytes_to_read = client.available();
            if (bytes_to_read) //如果有可读数据
            {
                if(bytes_to_read > DATA_BUF_SIZE)
                {
                    bytes_to_read = DATA_BUF_SIZE;
                }

                data.len = client.read(data.buf,bytes_to_read);
                if(data.len>0)
                {
                    xQueueSend(xQueueTCP,&data,0);    
                }
            }
            else
            {
                if(xQueueReceive(xQueueSerial,&data,2)==pdPASS)
                {          
                    client.write(data.buf,data.len);             
                    client.flush();            
                }
            }
        }
    }
}

/***************************************************************************/

/**
 * @brief 
 * 
 */
void setup()
{
    Serial.begin(115200);

    serialPort1.begin(115200, SERIAL_8N1, RXD_IO, TXD_IO);

    Serial.print("Mac:");
    Serial.println(WiFi.macAddress());

    led_init();

    Serial.println("STA_ENABLE");

    xQueueSerial = xQueueCreate(QUEUE_ITEM_NUM,sizeof(Data));
    xQueueTCP = xQueueCreate(QUEUE_ITEM_NUM,sizeof(Data));

    xTaskCreatePinnedToCore(serial_task, "serial_task", 8192, NULL, 10, &xSerialTask, 0);
    xTaskCreatePinnedToCore(tcp_task, "tcp_task", 8192, NULL, 10, &xTcpTask, 1);
}

/**
 * @brief 
 * 
 */
void loop()
{
    char buf[100];
    static int udp_send_count=0;

    if(WiFi.status() == WL_CONNECTED)
    {
        memset(buf,0,sizeof(buf));
        udp_send_count++;
        itoa(udp_send_count, (char *)buf, 10);
        udp.beginPacket("192.168.4.1",8001);
        String str_count;
        String str =WiFi.localIP().toString() + " " + WiFi.macAddress() + " " + String(buf);
        udp.print(str);
        udp.endPacket();
    
        int packetSize = udp.parsePacket();
        if (packetSize) 
        {
            memset(buf,0,sizeof(buf));
            int len = udp.read(buf, 100);
            if (len > 0) 
            {
                buf[len] = 0; // 为字符串添加结束符
            }
            //Serial.printf("UDP recv: %s\r\n", buf);
            timeout = 0;
        }

        timeout++;
        if(timeout > 10)
        {
            esp_restart();
        }

    }
    delay(500); 
}



